package ltd.smallwang.app.tool;

import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.cola.exception.BizException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ltd.smallwang.client.tool.api.ToolService;
import ltd.smallwang.client.tool.dto.EmailVerifyCodeQry;
import ltd.smallwang.infrastructure.exception.CommonErrorCode;
import ltd.smallwang.infrastructure.exception.ToolErrorCode;
import org.apache.commons.lang3.RandomStringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import java.text.MessageFormat;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
@RequiredArgsConstructor
public class ToolServiceImpl implements ToolService {

  private final RedissonClient redissonClient;

  private final JavaMailSender mailSender;

  private final MailProperties mailProperties;

  @Override
  public String emailVerifyCode(EmailVerifyCodeQry emailVerifyCodeQry) {
    // 1. 并发校验
    String email = emailVerifyCodeQry.getEmail();
    String appId = emailVerifyCodeQry.getAppId();
    String lockKey = MessageFormat.format("email_verify_code_{0}_{1}", email, appId);
    RLock lock = redissonClient.getLock(lockKey);
    if (lock.isLocked()) {
      log.warn("get email verify code failed, preview generate is not done");
      throw new BizException(ToolErrorCode.VERIFY_CODE_GENERATING.getErrorCode(),
          ToolErrorCode.VERIFY_CODE_GENERATING.getErrorMessage());
    }
    lock.lock(60, TimeUnit.SECONDS);

    // 2. 业务
    MimeMessage mimeMessage = mailSender.createMimeMessage();
    try {
      MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
      mimeMessageHelper.setTo(email);
      mimeMessageHelper.setFrom(mailProperties.getUsername());
      mimeMessageHelper.setSubject(appId + "验证码");
      String verifyCode = RandomStringUtils.randomNumeric(6);
      Map<String, Object> data = HashMap.newHashMap(8);
      data.put("username", emailVerifyCodeQry.getUsername());
      data.put("app_id", appId);
      data.put("email", email);
      data.put("verify_code", verifyCode);
      String emailContent = getEmailVerifyCodeContent("email_verify_code.ftl", data);
      mimeMessageHelper.setText(emailContent, true);
      mailSender.send(mimeMessage);

      // 3. 缓存至redis
      String cacheKey = appId + "_" + DigestUtil.sha256Hex(email) + "_" + verifyCode;
      redissonClient.getBucket(cacheKey).set(true, Duration.ofMinutes(5));

      return verifyCode;
    } catch (MessagingException e) {
      throw CommonErrorCode.SYSTEM_ERROR.buildBizException();
    }
  }

  private String getEmailVerifyCodeContent(String templateName, Map<String, Object> data) {
    Configuration configuration = new Configuration(Configuration.VERSION_2_3_32);
    configuration.setClassForTemplateLoading(this.getClass(), "/freemarker");
    try {
      Template template = configuration.getTemplate(templateName);
      return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
    } catch (Exception e) {
      throw new BizException(CommonErrorCode.SYSTEM_ERROR.getErrorCode(),
          CommonErrorCode.SYSTEM_ERROR.getErrorMessage());
    }
  }
}
